package com.hahaliu.hahaliu.service.impl.video;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.hahaliu.hahaliu.common.utils.RedisUtil;
import com.hahaliu.hahaliu.mapper.VideoMapper;
import com.hahaliu.hahaliu.pojo.entity.Video;
import com.hahaliu.hahaliu.service.video.VideoStatsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

@Service
public class VideoStatsServiceImpl implements VideoStatsService {
	@Autowired
	private VideoMapper videoMapper;

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	@Qualifier("taskExecutor")
	private Executor taskExecutor;

	/**
	 * 更新指定字段
	 * @param vid   视频ID
	 * @param column    对应数据库的列名
	 * @param increase  是否增加，true则增加 false则减少
	 * @param count 增减数量 一般是1，只有投币可以加2
	 */
	@Override
	public void updateStats(Integer vid, String column, boolean increase, Integer count) {
		UpdateWrapper<Video> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("v_id", vid);
		if (increase) {
			updateWrapper.setSql(column + " = " + column + " + " + count);
		} else {
			// 更新后的字段不能小于0
			updateWrapper.setSql(column + " = CASE WHEN " + column + " - " + count + " < 0 THEN 0 ELSE " + column + " - " + count + " END");
		}
		videoMapper.update(null, updateWrapper);
		redisUtil.delValue("videoStats:" + vid);
	}

	@Override
	public Video getVideoStatsById(Integer vid) {
		Video video = redisUtil.getObject("videoStats:" + vid, Video.class);
		if (video == null) {
			video = videoMapper.selectById(vid);
			if (video != null) {
				Video finalVideo = video;
				CompletableFuture.runAsync(() -> {
					redisUtil.setExObjectValue("videoStats:" + vid, finalVideo);    // 异步更新到redis
				}, taskExecutor);
			} else {
				return null;
			}
		}
		return video;
	}

	/**
	 * 同时更新点赞和点踩
	 * @param vid   视频ID
	 * @param addGood   是否点赞，true则good+1&bad-1，false则good-1&bad+1
	 */
	@Override
	public void updateGoodAndBad(Integer vid, boolean addGood) {
		UpdateWrapper<Video> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("v_id", vid);
		if (addGood) {
			updateWrapper.setSql("good = good + 1");
			updateWrapper.setSql("bad = CASE WHEN bad - 1 < 0 THEN 0 ELSE bad - 1 END");
		} else {
			updateWrapper.setSql("bad = bad + 1");
			updateWrapper.setSql("good = CASE WHEN good - 1 < 0 THEN 0 ELSE good - 1 END");
		}
		videoMapper.update(null, updateWrapper);
		redisUtil.delValue("videoStats:" + vid);
	}
}
